package dk.cs.wolverine.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

import dk.cs.wolverine.shared.Answer;
import dk.cs.wolverine.shared.Question;
import dk.cs.wolverine.shared.ResultSet;
import dk.cs.wolverine.shared.Section;
import dk.cs.wolverine.shared.SelectQuestion;
import dk.cs.wolverine.shared.TextQuestion;

/**
 * This is the implementation of the page used to show the sections, questions
 * and thanks page to the user
 * 
 * @author Kalle
 * 
 */
public class Questionnaire implements EntryPoint {

	private QuestionnaireServiceAsync server = GWT.create(QuestionnaireService.class);
	public ArrayList<Section> sections;
	public ResultSet resultset; 
	public HashMap<Question, String> alreadyAnswered;
	public ArrayList<Question> sectionQuestions;
	public Question currentQuestion;
	public RadioButton radio;
	public TextArea text;
	public VerticalPanel vp;
	public Section currentSection;
	public int currentSectionNr;
	public int currentIndex;
	private String previousHistoryToken;
	private ArrayList<RadioButton> radiobuttons;
	public TabBar tabBar;

	@Override
	public void onModuleLoad() {
		
		//Gets all sections from the server. 
		server.getSections(new AsyncCallback<ArrayList<Section>>() {
			@Override
			public void onSuccess(ArrayList<Section> sectionList) {
				System.out.println("RECIEVING SIZE " + sectionList.size());
				sections = sectionList; //saves the sections in a list. 
				System.out.println("SECTION SIZE " + sections.size());
				printSections(); //prints the sections on the page. 

			}
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("ERROR GETTING SECTIONS\n"+caught.getMessage());
			}
		});
		
		//Checks whether there is a userName in the cookies 
		String userCookieValue = Cookies.getCookie("QuestionnaireUsername");
		if(userCookieValue == null){
			showUserDialog(); //If we have no userName in the cookies, then we show a dialogbox
		}

		//sections = buildTestSection();
		//printSections();		
	}

	/**
	 * Display a TabBar with all sections. 
	 */
	public void printSections() {
		tabBar = new TabBar();

		//Adds the sections to the Tabbar.
		for(Section section : sections){
			tabBar.addTab(section.getName());
		}

		//Adds selecttionhandler to the Tabbar, to make it possible to change section.
		tabBar.addSelectionHandler(new SelectionHandler<Integer>() {
			@Override
			public void onSelection(SelectionEvent<Integer> event) {
				if(event == null){
					return;
				};
				if(currentSectionNr != event.getSelectedItem()){
					History.newItem("section:"+event.getSelectedItem());
					currentSectionNr = event.getSelectedItem();
				}
				getSectionQuestions(sections.get(event.getSelectedItem()));
			}
		});

		//Adds the Tabbar to the site. 
		RootPanel.get("sections").add(tabBar);
	}

	/**
	 * Gets the question to the section.
	 * @param section
	 */
	public void getSectionQuestions(Section section) {
		//Gets the resultset to the section. 
		server.getResultSet(Cookies.getCookie("QuestionnaireUsername"), new AsyncCallback<ResultSet>() {
			@Override
			public void onFailure(Throwable caught) {Window.alert("ERROR GETTING RESULTSET");}
			@Override
			public void onSuccess(ResultSet result) {				
				resultset = result;
			}
		});

		
		currentSection = section; //save the current section. 
		sectionQuestions = section.getQuestions(); //Gets the section questions 
		if(resultset != null)
			alreadyAnswered = resultset.getQuestionMap(section); //Gets our previous answers.
		
		if(!sectionQuestions.isEmpty()) {
			showQuestion(0); //We the section contains some questions we present the first one. 
		} else {
			RootPanel.get("content").clear();
			RootPanel.get("content").add(new HTML("No question in this section"));
		}
	}

	/**
	 * Display the question. 
	 * @param questionIndex
	 */
	public void showQuestion(final int questionIndex) {
		assert questionIndex < sectionQuestions.size() && questionIndex >= 0: "WE SHOULD NOT GET THIS FAR";

		currentIndex = questionIndex; //Save the current question index 
		currentQuestion = sectionQuestions.get(questionIndex); //Gets the current question.
		String question;
		if(currentQuestion.isTextQuestion()) {
			question = currentQuestion.getTextQuestion().getQuestion(); 
		} else {
			question = currentQuestion.getSelectQuestion().getQuestion();
		}
		
		// Create new verticalPanel panel and add the question and buttons to it. 
		vp = new VerticalPanel();
		vp.setBorderWidth(1);
		vp.setWidth("500px");
		vp.add(new HTML(question + "?"));
		if(currentQuestion.isTextQuestion()) {
			text = new TextArea();
			text.setName(question);
			text.setTitle("Please enter your answer");
			text.setWidth("450px");
			text.setHeight("150px");
			
			//Checks whether the user have already answered the question. 
			if(alreadyAnswered != null && alreadyAnswered.containsKey(currentQuestion))
				text.setValue(alreadyAnswered.get(currentQuestion)); //Add the answer from the resultset
			vp.add(text);
		} else if(currentQuestion.isSelectQuestion()){
			SelectQuestion q = currentQuestion.getSelectQuestion();
			radiobuttons = new ArrayList<RadioButton>();
			for (Answer answer : q.getAnswers()) {
				radio = new RadioButton(q.getSection().getName(), answer.getAnswer());
				if(alreadyAnswered != null && alreadyAnswered.containsKey(currentQuestion)) {
					if(answer.equals(alreadyAnswered.get(currentQuestion))) //Change to answer from resultset
						radio.setValue(true);
				}
				vp.add(radio);
				radiobuttons.add(radio);
			}
		}

		RootPanel.get("question").clear();
		RootPanel.get("question").add(vp);

		HorizontalPanel hp = new HorizontalPanel();
		hp.setWidth("300px");

		//Adds previous button if not first question. 
		if(questionIndex != 0) {
			Button prev = new Button();
			prev.setText("Previous");
			prev.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					History.back();			
				}
			});
			hp.add(prev);
		}
		//Create next button. 
		final Button next = new Button();

		//Sets the corresponding name to the button
		if(questionIndex != sectionQuestions.size()-1) next.setText("Next"); else next.setText("Finish");

		//Add clickhandler to the button
		next.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				int nextItem = questionIndex+1;
				if(currentQuestion.isSelectQuestion()){
					boolean hasBeenChecked = false;
					for (RadioButton rb : radiobuttons) {
						if(rb.getValue()) {
							hasBeenChecked = true;
							resultset.addAnswer(currentQuestion, rb.getText()); //adds the answer to the resultset 
						}
					}
					if(hasBeenChecked){
						if(next.getText().equals("Next")){
							History.newItem("section:"+currentSectionNr+"&question:"+nextItem);
							showQuestion(nextItem); 
						}else{ 
							History.newItem("section:"+currentSectionNr);
							finishQuestion();
						}
					}else{
						Window.alert("Please select an answer");
					}
				}else{
					if(text.getText().isEmpty()){
						Window.alert("Please give an answer");
					}else{
						if(next.getText().equals("Next")){
							History.newItem("section:"+currentSectionNr+"&question:"+nextItem);
							resultset.addAnswer(currentQuestion, text.getText()); //adds the answer to the resultset 
							showQuestion(nextItem); 
						}else{
							History.newItem("section:"+currentSectionNr);
							resultset.addAnswer(currentQuestion, text.getText()); //adds the answer to the resultset 
							finishQuestion();
						}
					}
				}

			}
		});
		hp.add(next);

		//Handle history. 
		History.addValueChangeHandler(new ValueChangeHandler<String>() {
			@Override
			public void onValueChange(ValueChangeEvent<String> event) {
				String historyToken = event.getValue();
				if(!historyToken.equalsIgnoreCase(previousHistoryToken)){
					previousHistoryToken = historyToken;
					try{
						if(historyToken.startsWith("section")){
							String[] token = historyToken.split("&");
							String[] firstToken = token[0].split(":");
							if("section".equalsIgnoreCase(firstToken[0])) 
								tabBar.selectTab(Integer.parseInt(firstToken[1]));
							if(token.length == 2){
								String[] secondToken = token[1].split(":");
								if("question".equalsIgnoreCase(secondToken[0])) 
									showQuestion(Integer.parseInt(secondToken[1]));
							}
						}else{
							tabBar.selectTab(0);
						}
					}catch (Exception e) {
						tabBar.selectTab(0);
					}
				}
			}
		});

		RootPanel.get("navigation").clear();
		RootPanel.get("navigation").add(hp);
	}

	/**
	 * Display when the question is finish. 
	 */
	public void finishQuestion() {
		RootPanel.get("question").clear();
		RootPanel.get("question").add(new HTML("Tak for din besvarelse"));
		RootPanel.get("navigation").clear();
	}

	/**
	 * Show the dialogbox to enter username. 
	 */
	public void showUserDialog() {
		final DialogBox dia = new DialogBox();
		dia.setTitle("Enter username");
		dia.setText("Enter username");
		dia.setSize("100px", "50px");
		VerticalPanel dialogcontent = new VerticalPanel();
		final TextBox user = new TextBox();
		dialogcontent.add(user);
		dialogcontent.add(new Button("Login", new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				String userName = user.getValue();
				Date now = new Date();
				long nowLong = now.getTime();
				nowLong = nowLong + (1000 * 60 * 60 * 2);//seven days
				now.setTime(nowLong);

				Cookies.setCookie("QuestionnaireUsername", userName, now);
				dia.hide();
			}
		}));
		dia.add(dialogcontent);
		dia.center();
	}

	@SuppressWarnings("unused")
	private ArrayList<Section> buildTestSection(){
		ArrayList<Section> sections = new ArrayList<Section>();

		Section sec = new Section("Skole");

		SelectQuestion sq = new SelectQuestion("Er skolen kedeligt?", null, sec);
		ArrayList<Answer> answers = new ArrayList<Answer>();
		answers.add(new Answer("Ja", 2, sq)); answers.add(new Answer("Nej", 10, sq)); answers.add(new Answer("Ved ikke", 50, sq));
		sq.setAnswers(answers);
		Question q = new Question(sq);
		sec.addQuestion(q);

		sq = new SelectQuestion("Er du altid i skole?", null, sec);
		answers = new ArrayList<Answer>();
		answers.add(new Answer("Ja", 2, sq)); answers.add(new Answer("Nej", 50, sq)); answers.add(new Answer("Ikke altid", 20, sq));
		q = new Question(sq);
		sec.addQuestion(q);

		TextQuestion tq = new TextQuestion("Hvad vil du gøre bedre ved din Skole", sec);
		q = new Question(tq);
		sec.addQuestion(q);

		tq = new TextQuestion("Følger du med i undervisningstimerne", sec);
		q = new Question(tq);
		sec.addQuestion(q);

		sections.add(sec);


		sec = new Section("Universitet");
		sq = new SelectQuestion("Hvad laver du på Universitet", null, sec);
		answers = new ArrayList<Answer>();
		answers.add(new Answer("Piller bussemænd", 40, sq)); answers.add(new Answer("Studere", 10, sq)); answers.add(new Answer("Ved ikke", 20, sq));
		q = new Question(sq);
		sec.addQuestion(q);

		sections.add(sec);

		return sections;
	}
}